package io.bdmc.common.utils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;

import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.Data;

@Data
public class FTPUtils {

    private static final Logger logger = LoggerFactory.getLogger(FTPUtils.class);
    private static String ip;
    private static String username;
    private static String password;
    private static FTPClient ftpClient;
    private static final int BUFFER_SIZE = 1024 * 1024 * 4;

    private static boolean connectServer() {
        boolean isSuccess = false;
        ftpClient = new FTPClient();
        try {
            ftpClient.connect(ip);
            isSuccess = ftpClient.login(username, password);
        } catch (IOException e) {
            // logger.error("连接FTP服务器异常", e);
        }
        return isSuccess;
    }

    /**
     * 下载ftp文件到磁盘
     * 
     * @param remotePath 远程文件路径
     * @param fileName   远程文件名
     * @return
     */
    private static String downloadFile(String remotePath, String fileName, String deviceSn) {
        InputStream result = null;
        String filePath = "";
        if (connectServer()) {
            try {
                int reply;
                reply = ftpClient.getReplyCode();
                if (!FTPReply.isPositiveCompletion(reply)) {
                    ftpClient.disconnect();
                    return null;
                }
                // 转移到FTP服务器目录
                // ftpClient.enterLocalPassiveMode();
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.setBufferSize(BUFFER_SIZE);
                boolean changeDir = ftpClient.changeWorkingDirectory(remotePath);
                if (changeDir) {
                    ftpClient.enterLocalPassiveMode();
                    result = ftpClient.retrieveFileStream(new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));
                    if (result == null)
                        return "";
                    byte[] bytes = IOUtils.toByteArray(result);
                    result.close();
                    ftpClient.completePendingCommand();
                    filePath = saveStreamToDisk(bytes, fileName, deviceSn);
                    return filePath;
                }

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException ioe) {
                    }
                }
            }
        }
        return filePath;
    }

    /**
     * 保存字节流到磁盘
     * 
     * @param buffer   字节流
     * @param fileName 原始文件名
     * @param deviceSn 设备sn
     * @return
     */
    public static String saveStreamToDisk(byte[] buffer, String fileName, String deviceSn) {
        if(buffer==null||buffer.length==0){
            return "";
        }
        String filePath = "";
        try {
            File path = new File(Constant.EXPORTPATH + "/sor/");
            if (!path.exists()) {
                path.mkdir();
            }
            String localFileName = deviceSn + "_"
                    + DateUtils.formatLocalDateTime(LocalDateTime.now(), DateUtils.Pay_DATE_TIME_PATTERN) + "_"
                    + fileName;
            File dir = new File(path.getAbsolutePath());
            if (!dir.exists()) {
                dir.mkdir();
            }
            File f = new File(path.getAbsolutePath(), localFileName);

            logger.info(fileName + "------ftp_sor_size:" + buffer.length);

            OutputStream oStream = new FileOutputStream(f);
            oStream.write(buffer);
            oStream.close();
            filePath = "/sor/" + localFileName;
            logger.info("下载完成，本地文件名:" + localFileName);
            return filePath;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return filePath;
    }

    /**
     * 下载ftp文件
     * 
     * @param remotePath  远程ftp文件夹路径 /ram/
     * @param fileName    文件名
     * @param ftpIp       IP地址
     * @param ftpUsername ftp用户名
     * @param ftpPwd      ftp密码
     * @return
     */
    // public static String downFile(String remotePath, String fileName, String
    // ftpIp, String ftpUsername, String ftpPwd) {
    // ip = ftpIp;
    // username = ftpUsername;
    // password = ftpPwd;
    // String filePath = downloadFile(remotePath, fileName);
    // return filePath;
    // }

    public static String downFile(String remotePath, String fileName, String deviceSn, String ftpIp, String ftpUsername,
            String ftpPwd) {
        ip = ftpIp;
        username = ftpUsername;
        password = ftpPwd;
        String filePath = downloadFile(remotePath, fileName, deviceSn);
        return filePath;
    }

    /**
     * 上传文件
     * 
     * @param localFile         本地文件
     * @param remoteUpLoadePath 上传路径
     * @return
     */
    public static boolean uploadFile(String localFile, String remoteUpLoadePath, String ftpIp, String ftpUsername,
            String ftpPwd) {
        ip = ftpIp;
        username = ftpUsername;
        password = ftpPwd;
        return uploadFile(new File(localFile), remoteUpLoadePath);
    }

    /***
     * 上传Ftp文件
     * 
     * @param localFile                当地文件
     * @param remoteUpLoadePath 上传服务器路径 - 应该以/结束
     */
    public static boolean uploadFile(File localFile, String remoteUpLoadePath) {
        if (!connectServer()) {
            logger.debug("连接FTP服务器失败.....");
            return false;
        }
        BufferedInputStream inStream = null;
        boolean success = false;
        try {
            inStream = new BufferedInputStream(new FileInputStream(localFile));
            createDirectory(remoteUpLoadePath);
            // 项目集成调用StreamUtil方法来实现
            if (logger.isDebugEnabled())
                logger.debug(localFile.getName() + "开始上传.....");
            success = ftpClient.storeFile(localFile.getName(), inStream);
            if (success == true) {
                if (logger.isDebugEnabled())
                    logger.debug(localFile.getName() + "上传成功");
                return success;
            }
        } catch (FileNotFoundException e) {
            logger.error(localFile + "未找到");
        } catch (IOException e) {
            logger.error("上传文件IO出错！" + e.toString());
        } finally {
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /**
     * 根据路径进行创建文件，解决兼容问题
     * 
     * @param path
     * @return
     * @throws IOException
     * @throws UnsupportedEncodingException
     */
    public static boolean createDirectory(String path) throws UnsupportedEncodingException, IOException {
        path = converPath(path);
        String directory = path.substring(0, path.lastIndexOf("/") + 1);
        if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) {
            // 如果远程目录不存在，则递归创建远程服务器目录
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            while (true) {
                String subDirectory = path.substring(start, end);
                if (!ftpClient.changeWorkingDirectory(subDirectory)) {
                    if (ftpClient.makeDirectory(subDirectory)) {
                        ftpClient.changeWorkingDirectory(subDirectory);
                    } else {
                        if (logger.isDebugEnabled())
                            logger.debug("创建目录失败!");
                        return false;
                    }
                }
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return true;
    }

    /**
     * 增加目录结尾标识“/”
     * 
     * @param path
     * @return
     */
    private static String converPath(String path) {
        if (!path.trim().endsWith("/"))
            path = path + "/";
        return path;
    }

    /**
     * 删除单个文件
     * 
     * @param filePath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String filePath) {
        filePath = Constant.EXPORTPATH + filePath;
        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
}